package com.dudu.service.impl;

import java.util.Calendar;

import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.dudu.access.EcpUtils;
import com.dudu.access.IMSTXUtils;
import com.dudu.access.ImsUtils;
import com.dudu.bean.AccountBean;
import com.dudu.bean.AppExtendBean;
import com.dudu.bean.ChargingRuleBean;
import com.dudu.bean.MeetInfoBean;
import com.dudu.bean.PoolAbilityInfoBean;
import com.dudu.enumeration.AbilityTypeEnum;
import com.dudu.service.IConferenceCallService;
import com.dudu.service.IConferenceManageInfoService;
import com.dudu.service.ILogService;
import com.dudu.service.IOperationPlatformService;
import com.dudu.service.IRecordInfoService;
import com.dudu.service.IRuleService;
import com.dudu.timer.SendVoiceUtil;
import com.dudu.utils.DateUtils;
import com.dudu.utils.ProperyResource;
import com.huawei.mediax.webservice.types.CreateScheduleConferenceResponseDocument;
import com.huawei.mediax.webservice.types.InviteAllSubscriberResponseDocument;
import com.huawei.mediax.webservice.types.LoginResult;

import core.CoreDao;
import core.CoreDaoInvoke;

/**
 * 多方通话--发起通话
 * 
 * @author weidong
 * 
 */
public class ConferenceCallServiceImpl implements IConferenceCallService {
    private static final Logger log = core.util.Logger.getLogger(ConferenceCallServiceImpl.class.getSimpleName());
    // 录音文件处理
    private IRecordInfoService recordInfoServiceImpl = new RecordInfoServiceImpl();
    // 能力配置查询
    private IRuleService ruleService = new RuleServiceImpl();
    // 用于查询数据用
    private CoreDao coreDao = CoreDaoInvoke.getInstance();
    // 用于记录通话相应信息
    private IConferenceManageInfoService conferenceManageInfoService = new ConferenceManageInfoServiceImpl();
    // 运营平台接口
    private IOperationPlatformService operationPlatformService = new OperationPlatformServiceImpl();
    // 通话日志
    private ILogService logService = new LogService();
    // IMS智能多方通话发起会议人数限制
    private int CALLNUMBER = 12;

    // IMS专业会议发起会议持续最大时间
    private long SOAP_TIME = 30 * 60 * 1000;
    // IMS专业会议最大人数上限
    private int SOAP_MAXCOUNT = 10;
    // IMS专业会议会议主题
    private String SOAP_SUBJECT = "用友通信-电话会议";

    /**
     * 用于发起多方通话-根据后台配置，控制发起通话的通道
     * 
     * @param appExtendBean
     *            应用扩展信息实体类
     * @param accountBean
     *            账号实体类
     * @param presenterNbr
     *            主叫
     * @param calledNbr
     *            被叫
     * @param userIdentify
     *            用户标识
     * @param tts_content
     *            多方通话前导音
     * @param display_mode
     *            被叫号码显示模式：0为显示配置号码、1为显示主叫号码
     * @param displayNbr
     *            来电显示号码（主叫显示号码）可为空，为空循环读取
     * @param usePlatNbr
     *            强制使用平台号码
     * @return
     */
    @Override
    public JSONObject doCall(AppExtendBean appExtendBean, AccountBean accountBean, String presenterNbr, String calledNbr, String userIdentify, String tts_content, String isRecord,
	    String display_mode, String displayNbr, String usePlatNbr) {
	log.info("CallConferenceServiceImpl.doCall--发起多方通话");
	// 用于后期返回值
	JSONObject object = new JSONObject();
	// 获取多方通话能力类型标识
	String abilityType = AbilityTypeEnum.MPTY.getKey();
	// 获取账号能力配置
	ChargingRuleBean chargingRule = ruleService.queryChargingRule(appExtendBean.getApp_key(), accountBean.getCust_account(), abilityType);
	// 判断查询的默认通道调用数据是否为空
	if (chargingRule != null) {
	    // 根据查询的账户默认调用的能力配置，调用相应的通道
	    String displayNum = null;// 显号
	    String number_vest = null;// 地区
	    String pool_ability_id = null;
	    SendVoiceUtil sendUtil = new SendVoiceUtil();
	    PoolAbilityInfoBean poolAbilityInfo = sendUtil.queryPoolAbilityInfo(coreDao, appExtendBean.getApp_key(), accountBean.getCust_account(), chargingRule.getType(),
		    pool_ability_id, displayNum, usePlatNbr, number_vest);
	    if (poolAbilityInfo == null) {
		if (AbilityTypeEnum.RONGLIANAUDEO.getKey().equals(chargingRule.getType())) {
		    poolAbilityInfo = new PoolAbilityInfoBean();
		} else {
		    object.put("result", "-1");
		    object.put("errorMsg", "未配置对应显号;ability_type:" + chargingRule.getType());
		    object.put("describe", "未配置显号");
		    object.put("code", "0018");
		    object.put("sessionId", "");
		    object.put("displayNbr", "");
		    return object;
		}
	    }
	    // 发起多方通话
	    // 判断如果是ims多方通话，则调用ims多方通话接口
	    if (AbilityTypeEnum.TALKSV2.getKey().equals(chargingRule.getType())) {
		// 发起IMS智能多方通话
		object = doCallTalksV2(poolAbilityInfo, appExtendBean, accountBean, userIdentify, presenterNbr, calledNbr, AbilityTypeEnum.TALKSV2.getKey(), tts_content, isRecord,
			display_mode, usePlatNbr);
	    } else if (AbilityTypeEnum.ECPMEET.getKey().equals(chargingRule.getType())) {
		// 判断如果是ECP多方通话，则调用ECP多方通话接口
		log.info("发起ECP多方通话：" + presenterNbr);
		object = doCallECP(poolAbilityInfo, appExtendBean, accountBean, userIdentify, presenterNbr, calledNbr, AbilityTypeEnum.ECPMEET.getKey());
	    } else if (AbilityTypeEnum.SCONFERENCE.getKey().equals(chargingRule.getType())) {
		log.info("发起IMS专业会议：" + presenterNbr);
		object = doCallSOAP(poolAbilityInfo, appExtendBean, accountBean, userIdentify, presenterNbr, calledNbr, AbilityTypeEnum.SCONFERENCE.getKey());
	    } else {
		object.put("result", "-1");
		object.put("errorMsg", "未配置对应通道！voice_type:" + abilityType);
		object.put("describe", "未配置线路");
		object.put("code", "0010");
		object.put("sessionId", "");
		object.put("displayNbr", "");
	    }

	} else {
	    object.put("result", "-1");
	    object.put("errorMsg", "未找到相应的能力配置！");
	    object.put("describe", "能力配置错误");
	    object.put("code", "0013");
	    object.put("sessionId", "");
	    object.put("displayNbr", "");
	}

	return object;
    }

    /**
     * 用于调用发起IMS智能多方通话用方法
     * 
     * @param appExtendBean
     *            应用扩展信息实体类
     * @param accountBean
     *            账号实体类
     * @param userIdentify
     *            用户标识
     * @param presenterNbr
     *            主叫
     * @param callees
     *            被叫
     * @param callType
     *            能力标识
     * @param tts_content
     *            多方通话前导音
     * @param display_mode
     *            被叫号码显示模式：0为显示配置号码、1为显示主叫号码
     * @param displayNbr
     *            来电显示号码（主叫显示号码）可为空，为空循环读取
     * @param usePlatNbr
     *            强制使用平台号
     * @return
     */
    private JSONObject doCallTalksV2(PoolAbilityInfoBean poolAbilityInfo, AppExtendBean appExtendBean, AccountBean accountBean, String userIdentify, String presenterNbr,
	    String callees, String callType, String tts_content, String isRecord, String display_mode, String usePlatNbr) {
	// 用于后面返回值
	JSONObject object = new JSONObject();
	try {
	    // 判断被叫号码数量
	    String[] calleeStr = callees.split(",");
	    // 判断号码数量，小于限制数量
	    if (calleeStr != null && calleeStr.length < CALLNUMBER) {
		// 发起多方通话
		// ----------------因需要压力测试，因此将实际调用IMS发起通话功能暂时去掉，后期需要加回---------------
		object = ImsUtils.talksV2(presenterNbr, callees, poolAbilityInfo, display_mode, tts_content, isRecord);
		// 判断发起通话是否成功
		if (!"0".equals(object.optString("result"))) {
		    object.put("result", "-1");
		    object.put("errorMsg", object.optString("describe"));
		    object.put("describe", "多方通话呼叫失败");
		    object.put("code", "0302");
		    object.put("sessionId", "");
		    object.put("displayNbr", "");
		} else {
		    String messages = "会议发起成功";
		    // 在运营平台注册用户信息
		    if (!operationPlatformService.manageUserByOP(appExtendBean.getPeriphery_code(), accountBean.getCust_account(), userIdentify)) {
			messages = messages + ",在运营平台注册用户信息失败！";
		    }
		    // 会议sessionId为
		    String sessionId = object.optString("sessionId");
		    // 存储会议信息
		    // 拼写会议信息bean
		    MeetInfoBean meetInfoBean = new MeetInfoBean();
		    meetInfoBean.setAbility_type(callType);
		    meetInfoBean.setApp_key(appExtendBean.getApp_key());
		    meetInfoBean.setCalled(callees);
		    meetInfoBean.setCaller(presenterNbr);
		    meetInfoBean.setChargeNumber(poolAbilityInfo.getCharge_number());
		    meetInfoBean.setComments(tts_content);
		    meetInfoBean.setCust_account(accountBean.getCust_account());
		    meetInfoBean.setDuration(0);
		    meetInfoBean.setPeriphery_code(appExtendBean.getPeriphery_code());
		    meetInfoBean.setSession_id(sessionId);
		    meetInfoBean.setStatus("0");
		    // 计算人数
		    String[] calledNumbers = callees.split(",");
		    meetInfoBean.setTotal_amount(calledNumbers.length + 1);
		    meetInfoBean.setUser_identify(userIdentify);

		    if (!conferenceManageInfoService.manageMeetInfo(meetInfoBean)) {
			messages = messages + ",会议信息存储失败！";
		    }
		    // 处理录音文件信息
		    if ("1".equals(isRecord)) {
			this.recordInfoServiceImpl.insert(coreDao, object.optString("sessionId"), AbilityTypeEnum.CALLRECORDER_IMS.getKey(), appExtendBean, accountBean);
		    }

		    // 将拼好的返回信息插入object
		    object.put("describe", messages);
		}
	    } else {
		object.put("result", "-1");
		object.put("errorMsg", "参会人员不能超过" + CALLNUMBER + "人");
		object.put("describe", "多方通话参会人员不能超过12人");
		object.put("code", "0303");
		object.put("sessionId", "");
		object.put("displayNbr", "");
	    }
	    // }
	} catch (Exception e) {
	    object.put("result", "-1");
	    object.put("errorMsg", "会议发起失败" + e.getMessage());
	    object.put("describe", "多方通话异常");
	    object.put("code", "0301");
	    object.put("sessionId", "");
	    object.put("displayNbr", "");
	}
	return object;
    }

    /**
     * 用于调用发起IMS专业会议方法
     * 
     * @param appExtendBean
     *            应用扩展信息实体类
     * @param accountBean
     *            账号实体类
     * @param userIdentify
     *            用户标识
     * @param presenterNbr
     *            主叫
     * @param callees
     *            被叫
     * @param callType
     *            能力标识
     * @return
     */
    private JSONObject doCallSOAP(PoolAbilityInfoBean poolAbilityInfo, AppExtendBean appExtendBean, AccountBean accountBean, String userIdentify, String caller, String callees,
	    String callType) {
	// 用于后面返回值
	JSONObject object = new JSONObject();
	// 判断相应参数是否为空
	if (StringUtils.isBlank(caller) || StringUtils.isBlank(callees)) {
	    object.put("result", "-1");
	    object.put("describe", "主持人号码、参与人号码不能为空");
	    object.put("code", "0020");
	} else {
	    // 华为登录实体类
	    LoginResult loginResult = null;
	    // 用于记录发起会话所用时间
	    // 开始时间的时间戳
	    long begin = 0;
	    // 结束时间的时间戳
	    long end = 0;
	    // 时间差值
	    double during;
	    // 通话发起时间
	    String currentTime = DateUtils.getCurrentTime();
	    try {
		if (ProperyResource.getAppId().equals("782")) {
		    loginResult = IMSTXUtils.login(poolAbilityInfo.getCharge_number(), poolAbilityInfo.getCharge_key());
		} else {
		    String username = ProperyResource.getSOAP_username();
		    String password = ProperyResource.getSOAP_password();
		    loginResult = IMSTXUtils.login(username, password);
		}

		log.info("IMS专业会议登录：" + loginResult.toString());
		// 判断登录是否成功
		if (loginResult != null && loginResult.getCode() == 200) {
		    // 获取登录时返回的sessionid
		    String sessionId = loginResult.getProfile().getSession();
		    try {
			// 开始时间
			begin = Calendar.getInstance().getTimeInMillis();
			// 创建会议

			int maxlen = 0;
			if (StringUtils.isBlank(callees)) {
			    maxlen = SOAP_MAXCOUNT;
			} else {
			    // 设置最大参会人数
			    maxlen = callees.split(",").length + SOAP_MAXCOUNT;
			}
			// 创建会议室
			CreateScheduleConferenceResponseDocument conferResDoc = IMSTXUtils.createSheduleConference(sessionId, SOAP_TIME, SOAP_SUBJECT, maxlen);
			// 获取会议标识
			String conferenceId = conferResDoc.getCreateScheduleConferenceResponse().getConference().getConferenceKey().getConferenceID();
			String pass = conferResDoc.getCreateScheduleConferenceResponse().getConference().getPasswordsArray()[0].getPassword();
			// 进行二次登录
			LoginResult login2 = IMSTXUtils.secondLogin(sessionId, conferenceId, pass);
			IMSTXUtils.subcribeConference(login2.getProfile().getSession(), conferenceId);

			// 邀请人员通话
			try {
			    // 进行邀请人员通话
			    InviteAllSubscriberResponseDocument doc = IMSTXUtils.InviteAllSubscriber(sessionId, conferenceId, caller + "," + callees);
			    // 结束时间
			    end = Calendar.getInstance().getTimeInMillis();
			    if (doc != null && doc.getInviteAllSubscriberResponse() != null) {
				if (doc.getInviteAllSubscriberResponse().getCode() == 200) {

				    String messages = "会议发起成功";
				    // 在运营平台注册用户信息
				    if (!operationPlatformService.manageUserByOP(appExtendBean.getPeriphery_code(), accountBean.getCust_account(), userIdentify)) {
					messages = messages + ",在运营平台注册用户信息失败！";
				    }
				    // 存储会议信息
				    // 拼写会议信息bean
				    MeetInfoBean meetInfoBean = new MeetInfoBean();
				    meetInfoBean.setAbility_type(callType);
				    meetInfoBean.setApp_key(appExtendBean.getApp_key());
				    meetInfoBean.setCalled(callees);
				    meetInfoBean.setCaller(caller);
				    meetInfoBean.setChargeNumber(callees);
				    meetInfoBean.setComments("");
				    meetInfoBean.setCust_account(accountBean.getCust_account());
				    meetInfoBean.setDuration(0);
				    meetInfoBean.setPeriphery_code(appExtendBean.getPeriphery_code());
				    meetInfoBean.setSession_id(sessionId);
				    meetInfoBean.setStatus("0");
				    // 计算人数
				    String[] calledNumbers = callees.split(",");
				    meetInfoBean.setTotal_amount(calledNumbers.length + 1);
				    meetInfoBean.setUser_identify(userIdentify);

				    if (!conferenceManageInfoService.manageMeetInfo(meetInfoBean)) {
					messages = messages + ",会议信息存储失败！";
				    }

				    // 将拼好的返回信息插入object
				    object.put("sessionId", conferenceId);
				    object.put("result", "0");
				    object.put("describe", messages);
				    object.put("code", "0000");
				    object.put("chairPassword", login2.getConferenceinfo().getPasswordsArray()[0].getPassword());
				    object.put("generalPassword", login2.getConferenceinfo().getPasswordsArray()[1].getPassword());
				    object.put("accessNumber", login2.getConferenceinfo().getAccessNumber().replace("+86", "0"));

				} else {
				    object.put("result", "-1");
				    object.put("describe", "邀请人失败");
				    object.put("code", "0022");
				}
			    } else {
				object.put("result", "-1");
				object.put("describe", "邀请人失败");
				object.put("code", "0022");
			    }
			} catch (Exception e) {
			    // 如果报错，则返回报错信息
			    object.put("result", "-1");
			    object.put("sessionId", sessionId + "-conferenceId：" + conferenceId);
			    object.put("describe", "专业会议邀请参会人失败：" + e.getMessage());
			    object.put("code", "0022");
			    e.printStackTrace();
			    return object;
			}
			// 发起通话的日志
			try {
			    during = Double.valueOf((end - begin)) / 1000;
			    // 获取发起通话的URL
			    StringBuffer urlBuffer = new StringBuffer("IMS专业会议");
			    // 拼相应的参数
			    urlBuffer.append("?appKey=");
			    urlBuffer.append(appExtendBean.getApp_key());
			    urlBuffer.append("&custAccount=");
			    urlBuffer.append(accountBean.getCust_account());
			    urlBuffer.append("&peripheryCode=");
			    urlBuffer.append(appExtendBean.getPeriphery_code());
			    urlBuffer.append("&phone=");
			    urlBuffer.append(caller + "," + callees);
			    logService.logIms(during, callType, urlBuffer.toString(), object.getString("describe"), object.getString("result"), currentTime, "SOAP", caller);
			} catch (Exception e) {
			    log.info("------IMS专业会议日志异常！----" + e);
			}
		    } catch (Exception e) {
			// 如果报错，则返回报错信息
			object.put("result", "-1");
			object.put("sessionId", loginResult.getProfile().getSession());
			object.put("describe", "专业会议创建会议失败：" + e.getMessage());
			object.put("code", "0022");
			log.info("------IMS专业会议日志异常！----" + e);
		    }
		} else {
		    // 如果报错，则返回报错信息
		    object.put("result", "-1");
		    object.put("sessionId", loginResult.getProfile().getSession());
		    object.put("describe", "IMS专业会议登陆失败");
		}
	    } catch (Exception e) {
		// 如果报错，则返回报错信息
		object.put("result", "0007");
		object.put("describe", "IMS专业会议登陆失败：" + e.getMessage());
		log.info("------IMS专业会议日志异常！----" + e);
	    }
	}
	return object;
    }

    /**
     * 用于调用发起ECP会议方法 显号为配置文件中，显号为17001090001,17001090002,17001097473
     * 
     * @param appExtendBean
     *            应用扩展信息实体类
     * @param accountBean
     *            账号实体类
     * @param userIdentify
     *            用户标识
     * @param caller
     *            主叫
     * @param callees
     *            被叫
     * @param callType
     *            能力标识
     * @return
     */
    private JSONObject doCallECP(PoolAbilityInfoBean poolAbilityInfo, AppExtendBean appExtendBean, AccountBean accountBean, String userIdentify, String caller, String callees,
	    String callType) {
	// 用于后面返回值
	JSONObject object = new JSONObject();
	// 判断相应参数是否为空
	if (StringUtils.isBlank(caller) || StringUtils.isBlank(callees)) {
	    object.put("result", "-1");
	    object.put("describe", "主持人号码、参与人号码不能为空");
	    object.put("code", "0020");
	} else {
	    // 用于记录发起会话所用时间
	    // 开始时间的时间戳
	    long begin = 0;
	    // 结束时间的时间戳
	    long end = 0;
	    // 时间差值
	    double during;
	    // 通话发起时间
	    String currentTime = DateUtils.getCurrentTime();
	    try {
		// 开始时间
		begin = Calendar.getInstance().getTimeInMillis();
		// 创建会议
		// 传入配置的ECP主显号码创建会议
		String response = EcpUtils.createConference(poolAbilityInfo.getDisplay_number());

		log.info("ECP发起通话创建会议返回：" + response);
		Document doc = DocumentHelper.parseText(response);
		Element root = doc.getRootElement();
		// 获取查询结果
		// 获取是否成功标识
		String results = root.elementTextTrim("result");
		// 获取会议标识
		String conferenceIdentifier = root.elementTextTrim("ConferenceIdentifier");
		// String SessionToken = root.elementTextTrim("SessionToken");
		if (results.equals("1100")) {
		    // 发起通话
		    String result = EcpUtils.inviteNumber(conferenceIdentifier, caller + "," + callees);
		    // 结束时间
		    end = Calendar.getInstance().getTimeInMillis();

		    // 获取返回值，判断返回是否调用成功
		    doc = DocumentHelper.parseText(result);
		    root = doc.getRootElement();
		    results = root.elementTextTrim("result");

		    // 发起通话的日志
		    try {
			during = Double.valueOf((end - begin)) / 1000;
			// 获取发起通话的URL
			StringBuffer urlBuffer = new StringBuffer(ProperyResource.getEcp_Status_Url());
			// 拼相应的参数
			urlBuffer.append("?ConferenceIdentifier=");
			urlBuffer.append(conferenceIdentifier);
			urlBuffer.append("&phone=");
			urlBuffer.append(caller + "," + callees);
			logService.logIms(during, callType, urlBuffer.toString(), result, results, currentTime, "ECP", caller);
		    } catch (Exception e) {
			log.info("------ECP发起电话会议日志异常！----");
		    }

		    log.info("通话请求返回：" + result);
		    // 判断发起通话是否成功
		    if (!"1100".equals(results)) {
			object.put("result", "-1");
			object.put("describe", "会议发起失败");
			object.put("code", "0022");
		    } else {

			String messages = "会议发起成功";
			// 在运营平台注册用户信息
			if (!operationPlatformService.manageUserByOP(appExtendBean.getPeriphery_code(), accountBean.getCust_account(), userIdentify)) {
			    messages = messages + ",在运营平台注册用户信息失败！";
			}
			// 存储会议信息
			// 拼写会议信息bean
			MeetInfoBean meetInfoBean = new MeetInfoBean();
			meetInfoBean.setAbility_type(callType);
			meetInfoBean.setApp_key(appExtendBean.getApp_key());
			meetInfoBean.setCalled(callees);
			meetInfoBean.setCaller(caller);
			meetInfoBean.setChargeNumber(callees);
			meetInfoBean.setComments("");
			meetInfoBean.setCust_account(accountBean.getCust_account());
			meetInfoBean.setDuration(0);
			meetInfoBean.setPeriphery_code(appExtendBean.getPeriphery_code());
			meetInfoBean.setSession_id(conferenceIdentifier);
			meetInfoBean.setStatus("0");
			// 计算人数
			String[] calledNumbers = callees.split(",");
			meetInfoBean.setTotal_amount(calledNumbers.length + 1);
			meetInfoBean.setUser_identify(userIdentify);

			if (!conferenceManageInfoService.manageMeetInfo(meetInfoBean)) {
			    messages = messages + ",会议信息存储失败！";
			}

			object.put("sessionId", conferenceIdentifier);
			object.put("result", "0");
			object.put("describe", messages);
			object.put("code", "0000");
		    }
		} else {
		    object.put("result", "-1");
		    object.put("describe", "会议发起失败:" + results);
		    object.put("code", "0022");
		}
	    } catch (Exception e) {
		// ECP会议发起异常
		object.put("result", "-1");
		object.put("describe", "会议发起失败:" + e.getMessage());
		object.put("code", "0022");
	    }
	}
	return object;
    }
}
